// package关键字：声明当前类所在的包，用于组织和管理代码
// com.itheima.polymorphsm3：包名，通常采用公司域名反写+项目名的形式
package com.itheima.polymorphsm3;

// public：访问修饰符，表示这个类可以被其他任何类访问
// class：关键字，用于定义一个类
// Test：类名，采用驼峰命名法，首字母大写
// 这个类用于测试多态的核心概念和使用规则
public class Test {
    // public：访问修饰符，表示这个方法可以被其他任何类访问
    // static：静态修饰符，表示这个方法属于类而不是对象
    // void：返回值类型，表示这个方法没有返回值
    // main：方法名，特殊的方法名，是Java程序的入口点
    // String[] args：参数列表，表示命令行参数数组
    public static void main(String[] args) {
        // 注释：说明这段代码的目的是认识多态的代码实现
        // 注释：多态的第一个好处是右边的具体对象可以灵活切换，实现了解耦合
        // Animal a1：声明一个Animal类型的引用变量a1
        // = new Tortoise()：创建一个Tortoise类型的对象，并赋值给a1
        // 这行代码体现了多态的核心：父类引用指向子类对象
        Animal a1 = new Tortoise();
        // a1.run()：调用a1的run方法
        // 多态下方法调用规则：编译看左边（检查Animal类是否有run方法），运行看右边（执行Tortoise类的run方法）
        a1.run();
        // 注释：这行代码被注释掉了，因为在多态情况下，父类引用不能直接调用子类独有的方法
        // a1.shrinkHead(); // 多态下的一个问题：多态下不能调用子类独有功能。

        // 注释：介绍强制类型转换的作用
        // Tortoise t1：声明一个Tortoise类型的引用变量t1
        // (Tortoise) a1：将a1强制转换为Tortoise类型
        // 强制类型转换可以解决多态下不能调用子类独有方法的问题
        Tortoise t1 = (Tortoise) a1;
        // t1.shrinkHead()：调用t1的shrinkHead方法
        // 现在t1是Tortoise类型，可以调用Tortoise类独有的方法
        t1.shrinkHead();

        // 注释：解释强制类型转换的编译时规则
        // 注释：解释强制类型转换的运行时风险
        // 注释：这行代码被注释掉了，因为a1实际引用的是Tortoise对象，不能转换为Wolf类型
        // 否则会抛出ClassCastException异常
        // Wolf w1 = (Wolf) a1;

        // System.out.println()：Java的输出语句
        // "======================="：输出分隔线，增强可读性
        System.out.println("=======================");

        // Wolf w：声明一个Wolf类型的引用变量w
        // = new Wolf()：创建一个Wolf类型的对象，并赋值给w
        Wolf w = new Wolf();
        // go(w)：调用静态方法go，并传入w作为参数
        // 这里体现了多态的另一个好处：父类类型的参数可以接收子类对象
        go(w);

        // Tortoise t：声明一个Tortoise类型的引用变量t
        // = new Tortoise()：创建一个Tortoise类型的对象，并赋值给t
        Tortoise t = new Tortoise();
        // go(t)：调用静态方法go，并传入t作为参数
        // 同一个方法可以处理不同的子类对象，体现了多态的扩展性
        go(t);
    } // main方法结束标记

    // public：访问修饰符，表示这个方法可以被其他任何类访问
    // static：静态修饰符，表示这个方法属于类而不是对象
    // void：返回值类型，表示这个方法没有返回值
    // go：方法名
    // Animal a：参数列表，接收Animal类型的参数（可以是Animal或其子类的对象）
    // 这个方法演示了多态作为方法参数的应用
    public static void go(Animal a){
        // System.out.println()：Java的输出语句
        // "开始。。。。。"：输出开始信息
        System.out.println("开始。。。。。");
        // a.run()：调用a的run方法
        // 多态下方法调用规则：编译看左边，运行看右边
        // 根据a实际引用的对象类型，执行相应类的run方法
        a.run();
        // 注释：这行代码被注释掉了，因为在多态情况下，父类引用不能直接调用子类独有的方法
        // a1.shrinkHead(); // 报错，多态下不能调用子类独有功能。
        // 注释：Java官方建议在进行强制类型转换前，先使用instanceof关键字判断对象的真实类型
        // if语句：条件判断
        // a instanceof Wolf：判断a引用的对象是否是Wolf类型
        // instanceof关键字可以避免ClassCastException异常
        if(a instanceof Wolf){
            // 如果a是Wolf类型，将其强制转换为Wolf类型
            Wolf w1 = (Wolf) a;
            // 调用Wolf类独有的eatSheep方法
            w1.eatSheep();
        }else if(a instanceof Tortoise){
            // 否则如果a是Tortoise类型，将其强制转换为Tortoise类型
            Tortoise t1 = (Tortoise) a;
            // 调用Tortoise类独有的shrinkHead方法
            t1.shrinkHead();
        } // if-else if语句结束标记
    } // go方法结束标记
} // Test类结束标记
